package com.djx;

import com.djx.locks.MyLock;
import com.djx.locks.Test00;
import com.djx.locks.TicketSeller;
import com.sun.media.sound.SoftTuning;
import org.apache.zookeeper.*;
import org.apache.zookeeper.data.Stat;
import org.junit.Test;

import javax.jws.Oneway;
import java.io.IOException;
import java.sql.SQLOutput;
import java.util.Collections;
import java.util.List;

public class lianxi {


    private final String myIP = "192.168.15.132:2181";
    private static final String fu = "/djxs";
    private static final String zi = "/djx_";
    private String lockPath;
    ZooKeeper zooKeeper;

    //构造
    public lianxi() {
        try {
            zooKeeper = new ZooKeeper(myIP, 10000, new Watcher() {
                public void process(WatchedEvent watchedEvent) {
                    if (watchedEvent.getType() == Event.EventType.None) {
                        if (Event.KeeperState.SyncConnected == watchedEvent.getState()) {
                            System.out.println("连接成功!!!!!!!!!");
                        }
                    }
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /***
     *创建临时节点
     */
    public void createNode() {
        try {
            //判断父节点是否存在
            Stat exists = zooKeeper.exists(fu, null);
            System.out.println("exists:::"+exists);
            //如果父节点不存在则创建 持久节点
            if (exists == null) {
                System.out.println("父节点为空!!");
                zooKeeper.create(fu, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                System.out.println("创建父节点成功!!!");
            }
            //创建临时有序节点
            lockPath = zooKeeper.create(fu + zi, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
            System.out.println("临时有序节点为::: " + lockPath);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Test
    public void ccb() {
        createNode();
    }

    /**
     * 监听器
     */
    Watcher watcher = new Watcher() {
        public void process(WatchedEvent watchedEvent) {
            //当节点删除时!
            if (watchedEvent.getType() == Event.EventType.NodeDeleted) {
                //锁住当前监听器
                synchronized (this) {
                    //释放锁
                    notifyAll();
                }
            }
        }
    };

    public void acquireLock() {
        //创建节点!
        createNode();
        //获取创建的锁
        getCreateNode();

    }

    //获取创建的锁
    private void getCreateNode() {
        try {
            //查询 子节点
            List<String> children = zooKeeper.getChildren(fu, false);
            //排序
            Collections.sort(children);

            //截取 子节点
//            indexOf  字符串最先出现的位置
            int i = children.indexOf(lockPath.substring(fu.length() + 1));
//            System.out.println("lockPath:"+lockPath+"      "+i);
            if (i == 0) {
                System.out.println("获取锁成功!!");
                return;
            }
            try {
                if (i == -1) {
                    System.out.println("!锁不存在 -1");
                    return;
                } else {  //他不是第一个 节点存在

                    //获取前面个节点的节点路径
                    String path = children.get(i - 1);
                    //判断前一个节点是否存在
                    Stat exists = zooKeeper.exists(fu + path, watcher);
                    //前面节点为空
                    if (exists == null) {
                        getCreateNode();
                    } else {
                        //说明上一个节点有可能在等待 就是没有释放锁
                        //锁住监听器
                        synchronized (watcher) {
                            watcher.wait();
                        }
                        //当锁释放了 代表上一个节点删除了 就继续获取节点
                        getCreateNode();
                    }

                }
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("!锁不存在 -1");
            }


        } catch (KeeperException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    //释放锁
    public void releaseLock() throws Exception {
        zooKeeper.delete(this.lockPath, -1);
        zooKeeper.close();
        System.out.println("锁释放::: " + this.lockPath);

    }

    /**
     * 测试
     */
    @Test
    public void cc() {
        acquireLock();
    }

}




